import json

import redis
from flask import current_app
from flask import jsonify
from flask import make_response
from flask import request
from flask.wrappers import Response

from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.services.authentication_service import AuthenticationService
from spiffworkflow_backend.services.monitoring_service import get_version_info_data


def test_raise_error() -> Response:
    raise Exception("This exception was generated by /debug/test-raise-error for testing purposes. Please ignore.")


def version_info() -> Response:
    return make_response(get_version_info_data(), 200)


# this is just to see what the protocol is, primarily. if the site is running on https in the browser, but this says "http://something.example.com",
# that might be bad, and might require some server configuration to make sure flask knows it is running on https.
# if using path based routing, the path will probably not be returned from this endpoint.
def url_info() -> Response:
    return make_response(
        {
            "request.root_path": request.root_path,  # type: ignore
            "request.host_url": request.host_url,
            "request.url": request.url,
            "cache": AuthenticationService.ENDPOINT_CACHE,
        },
        200,
    )


def celery_backend_results(
    process_instance_id: int,
    include_all_failures: bool = True,
) -> Response:
    redis_client = redis.StrictRedis.from_url(current_app.config["SPIFFWORKFLOW_BACKEND_CELERY_RESULT_BACKEND"])
    results: list = redis_client.keys("celery-task-meta-*")  # type: ignore
    if len(results) > 1000:
        raise ApiError(
            error_code="too_many_entries",
            message=f"There are too many redis entries. You probably shouldn't use this api method. count {len(results)}",
            status_code=400,
        )

    result_values = redis_client.mget(results)  # type: ignore

    return_body = []
    for value in result_values:
        if value is None:
            continue
        value_dict = json.loads(value.decode("utf-8"))
        if (
            value_dict["result"]
            and "process_instance_id" in value_dict["result"]
            and value_dict["result"]["process_instance_id"] == process_instance_id
        ) or (value_dict["status"] == "FAILURE" and include_all_failures is True):
            return_body.append(value_dict)

    return make_response(jsonify(return_body), 200)
